home *** CD-ROM | disk | FTP | other *** search
Text File | 2007-10-18 | 67.4 KB | 2,007 lines |
- // BEGIN FLOCK GPL
- //
- // Copyright Flock Inc. 2005-2007
- // http://flock.com
- //
- // This file may be used under the terms of of the
- // GNU General Public License Version 2 or later (the "GPL"),
- // http://www.gnu.org/licenses/gpl.html
- //
- // Software distributed under the License is distributed on an "AS IS" basis,
- // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- // for the specific language governing rights and limitations under the
- // License.
- //
- // END FLOCK GPL
-
- const ENABLE_DEBUG = true;
- function DEBUG(x) { if (ENABLE_DEBUG) debug("flockPhotobucketService: "+x+"\n"); }
-
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Cr = Components.results;
- const Cu = Components.utils;
-
- Cu.import("resource:///modules/FlockCryptoHash.jsm");
-
- const PHOTOBUCKET_TITLE = "PhotoBucket Web Service";
- const PHOTOBUCKET_FAVICON = "chrome://flock/content/services/photobucket/favicon.png";
- const PHOTOBUCKET_CID = Components.ID('{d3b147b0-a321-11da-a746-0800200c9a66}');
- const PHOTOBUCKET_CONTRACTID = "@flock.com/?photo-api-photobucket;1";
- const SERVICE_ENABLED_PREF = "flock.service.photobucket.enabled";
- const CATEGORY_COMPONENT_NAME = "Photobucket JS Component"
- const CATEGORY_ENTRY_NAME = "photobucket"
-
- const flockIError = Components.interfaces.flockIError;
- const flockIPhotoAlbum = Components.interfaces.flockIPhotoAlbum;
- const flockIPhotoPerson = Components.interfaces.flockIPhotoPerson;
-
- const FLOCK_PHOTO_ALBUM_CONTRACTID = "@flock.com/photo-album;1";
- const FLOCK_PHOTOPERSON_CONTRACTID = "@flock.com/photo-person;1";
- const FLOCK_ERROR_CONTRACTID = "@flock.com/error;1";
-
- const PHOTOBUCKET_API_VERSION = "1.0";
- const PHOTOBUCKET_TOKEN_PREF = "flock.photo.photobucket.token";
- const PHOTOBUCKET_SESSION_REFRESH_INTERVAL = 21600000; // every 6 hours refresh the session token
-
- const PHOTOBUCKET_PK = "e57335b0847da8b1105b6c8bc27d217a";
- const PHOTOBUCKET_SCID = "149825788";
- const PHOTOBUCKET_PROPERTIES = "chrome://flock/locale/services/photobucket.properties";
-
- // services
- const RDFS = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
- const IOS = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
- const RDFCU = Cc["@mozilla.org/rdf/container-utils;1"].getService(Ci.nsIRDFContainerUtils);
-
- var gCompTK;
- function getCompTK() {
- if (!gCompTK) {
- gCompTK = Cc["@flock.com/singleton;1"]
- .getService(Ci.flockISingleton)
- .getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
- .wrappedJSObject;
- }
- return gCompTK;
- }
-
- // for Cardinal to Danphe migration
- const FLOCK_NS = "http://flock.com/rdf#";
-
- // String defaults... may be updated later through Web Detective
- var gStrings = {
- "domains": "photobucket.com",
- "userloginURL": "http://photobucket.com/login.php",
- "userprofileURL": "http://photobucket.com/images/search/%accountid%",
- "serviceloginURL": "http://photobucket.com/svc/servicelogin.php",
- "apiURL": "http://photobucket.com/svc/api.php"
- };
-
- var gPhotobucketAPI;
-
- // ====================================================
- // ========== BEGIN General Helper Functions ==========
- // ====================================================
-
- function loadSubScript(spec)
- {
- var loader = Components.classes['@mozilla.org/moz/jssubscript-loader;1']
- .getService(Components.interfaces.mozIJSSubScriptLoader);
- var context = {};
- loader.loadSubScript(spec, context);
- return context;
- }
-
- function loadLibraryFromSpec(aSpec) {
- var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
- .getService(Components.interfaces.mozIJSSubScriptLoader);
- loader.loadSubScript(aSpec);
- }
-
- loadLibraryFromSpec("chrome://flock/content/common/flocksafe.js");
- loadLibraryFromSpec("chrome://browser/content/flock/photo/photoAPI.js");
-
-
- function photobucketPhoto() {
- }
-
- photobucketPhoto.prototype= {
- id: "",
- thumbnail: "",
- webPageUrl: "",
- midSizePhoto: "",
- largeSizePhoto: "",
- title: "",
- username: "",
- userid: "",
- is_video: "",
- svcShortName: 'photobucket',
-
- buildTooltip: function( ) {
- // do we have to use document from the window to ceate elements? -- ja
- var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- var win = wm.getMostRecentWindow('navigator:browser');
- if (!win) return null;
-
- var hbox = win.document.createElement('hbox');
- var box = win.document.createElement('vbox');
- box.setAttribute('style', 'max-width: 250px');
- var title = win.document.createElement('label');
- title.setAttribute('value', this.title );
- title.setAttribute('crop', 'end');
- box.appendChild(title);
- var lbl = win.document.createElement('label');
- lbl.setAttribute('value', this.username );
- lbl.setAttribute('class', 'user');
- box.appendChild(lbl);
- hbox.appendChild(box)
-
- var vbox = win.document.createElement('vbox');
- var cbox = win.document.createElement('hbox');
- var largeImg = win.document.createElement('image');
- largeImg.setAttribute('src', this.midSizePhoto);
- largeImg.setAttribute('style', 'margin-bottom: 2px;');
- var spacer = win.document.createElement('spacer');
- spacer.setAttribute('flex', '1');
- cbox.appendChild(largeImg);
- cbox.appendChild(spacer);
- vbox.appendChild(cbox);
- vbox.appendChild(hbox);
-
- return vbox;
- },
- buildHTML: function( ) {
- return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.midSizePhoto+'" border="0" /></a>';
- },
- buildLargeHTML: function( ) {
- return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.largeSizePhoto+'" border="0" /></a>';
- },
- buildBBCode: function ( ) {
- if(this.is_video)
- {
- return '[photob]' + this.largeSizePhoto + '[photob]'
-
- }else
- {
- return '[url=' + this.webPageUrl + '][img]'+ this.largeSizePhoto +'[/img][/url]';
- }
- },
- buildMiniPage: function ( ) {
- return '<html><head><title>' + this.title + ' (' + this.username + ')</title></head>' +
- '<body><object width="425" height="350">' +
- '<param name="movie" value="'+this.largeSizePhoto+'"/>' +
- '<center><embed src="'+this.largeSizePhoto+'&autoplay=1" type="application/x-shockwave-flash" width="425" height="350"/></object></center></body></html>';
- },
- QueryInterface: function(iid) {
- if (!iid.equals(Components.interfaces.nsISupports) &&
- !iid.equals(Components.interfaces.flockIPhoto)) {
- throw Components.results.NS_ERROR_NO_INTERFACE;
- }
- return this;
- }
- };
-
-
- // ====================================================
- // ========== BEGIN photobucketService class ==========
- // ====================================================
-
- function photobucketService()
- {
- this.obs = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- this.acUtils = Components.classes["@flock.com/account-utils;1"]
- .getService(Components.interfaces.flockIAccountUtils);
- this.url = "http://www.photobucket.com";
- this.initialized = false;
- this.logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
- this.logger.init("photobucket");
- this._ctk = {
- interfaces: [
- "nsISupports",
- "nsIClassInfo",
- "nsISupportsCString",
- "nsIObserver",
- "flockIPollingService",
- "flockIWebService",
- "flockIAuthenticateNewAccount",
- "flockIManageableWebService",
- "flockIMediaWebService"
- ],
- shortName: "photobucket",
- fullName: "Photobucket",
- description: PHOTOBUCKET_TITLE,
- favicon: PHOTOBUCKET_FAVICON,
- contractID: PHOTOBUCKET_CONTRACTID,
- accountClass: photobucketAccount,
- needPassword: false
- };
-
- var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]
- .getService(Components.interfaces.nsIStringBundleService);
- var bundle = sbs.createBundle(PHOTOBUCKET_PROPERTIES);
-
- this._channels = {
- "special:recent": {
- title: bundle.GetStringFromName("flock.photobucket.title.recent"),
- supportsSearch: false
- }
- };
-
- this.init();
- }
-
-
- // BEGIN nsIObserver interface
- photobucketService.prototype.observe =
- function photobucketService_observe(aSubject, aTopic, aData)
- {
- }
- // END nsIObserver interface
-
-
- photobucketService.prototype.shortName = "photobucket";
- photobucketService.prototype.serviceName = "Photobucket";
-
- photobucketService.prototype.getPhotoFromRDFNode =
- function (aRDFId)
- {
- var newPhoto = new photobucketPhoto();
- var coopPhoto = this.faves_coop.get(aRDFId);
- newPhoto.webPageUrl = coopPhoto.URL;
- newPhoto.thumbnail = coopPhoto.thumbnail;
- newPhoto.midSizePhoto = coopPhoto.midSizePhoto;
- newPhoto.largeSizePhoto = coopPhoto.largeSizePhoto;
- newPhoto.username = coopPhoto.username;
- newPhoto.userid = coopPhoto.userid;
- newPhoto.title = coopPhoto.name;
- newPhoto.id = coopPhoto.photoid;
- newPhoto.icon = coopPhoto.favicon;
- newPhoto.uploadDate = coopPhoto.datevalue;
- newPhoto.is_public = coopPhoto.is_public;
- newPhoto.is_video = coopPhoto.is_video;
- return newPhoto;
- }
-
- photobucketService.prototype.handlePhotosResult =
- function photobucketService_handlePhotosResult(aXML) {
- var inst = this;
- function createItem(media, is_video) {
- var uploadDate = media.getAttribute("uploaddate");
- var title = media.getAttribute("name");
- var username = media.getAttribute("username");
- var page_url = "";
- var thumb_url = media.getElementsByTagName('thumb')[0].firstChild.nodeValue;
- var small_url = media.getElementsByTagName('url')[0].firstChild.nodeValue;
- // this is a photobucket api issue - need a fix -
- try {
- page_url = media.getElementsByTagName('browseurl')[0].firstChild.nodeValue;
- page_url = page_url.replace('&', '&');
- }
- catch(e) {
- page_url = small_url;
- }
- var newPhoto = new photobucketPhoto();
- newPhoto.webPageUrl = page_url;
- newPhoto.thumbnail = thumb_url;
- newPhoto.midSizePhoto = thumb_url;
- newPhoto.largeSizePhoto = small_url;
- newPhoto.title = title;
- newPhoto.username = username;
- newPhoto.userid = username;
- if (uploadDate) {
- newPhoto.id = uploadDate;
- newPhoto.uploadDate = parseInt(uploadDate)*1000;
- } else {
- newPhoto.id = username + ":" + title;
- }
- newPhoto.is_video = is_video;
- newPhoto.has_miniView = is_video;
- return newPhoto;
- }
-
- try {
- var rval = [];
-
- var videoList = aXML.getElementsByTagName("video");
- for (var i = 0; i < videoList.length; i++) {
- rval.push(createItem(videoList[i], true));
- }
-
- var photoList = aXML.getElementsByTagName("photo");
- for (var i = 0; i < photoList.length; i++) {
- rval.push(createItem(photoList[i], false));
- }
- } catch(e) {
- inst.logger.error(e);
- }
-
- /*
- * do not sort anymore since PB no longer passes back the uploadDate.
- * instead we just present the photos in the order PB gives them to
- * us (upload order)
- * see https://bugzilla.flock.com/show_bug.cgi?id=9084
-
- // sort the photos and videos together by date
- // the follow sorts based on ID which we are using the uploadDate to be the id
- // it is ugly -- and probably not as efficient as it could be --- but it
- // is only sorting 20 items at most so it is good enough for now - ja
- rval.sort(function(a,b) {
- return (b.id-a.id);
- });
- */
-
- return rval;
- }
-
- photobucketService.prototype.getContacts =
- function photobucketService_getContacts(aListener)
- {
- return -1; // throw unsupported exception
- }
-
- photobucketService.prototype.findByUsername =
- function photobucketService_findByUsername(aListener, aUsername)
- {
- var inst = this;
- var myListener = {
- onResult: function (aXML) {
- //var user = aXML.getElementsByTagName("photo")[0];
- // We should be getting all the user's details from the response xml, but
- // the pbucket response has all pertinent info with the photo tag. If
- // there are no photos, then we have no user info
- var newUserObj = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID]
- .createInstance(flockIPhotoPerson);
- newUserObj.id = aUsername;
- newUserObj.username = aUsername;
- newUserObj.fullname = aUsername;
- newUserObj.service = inst;
- aListener.onFindByUsernameResult(newUserObj);
- },
- onError: function (aXML) {
- aListener.onError(aXML);
- }
- }
- var params = {};
- params.username = aUsername;
- var dict = params2Dictionary(params);
- this.api.authenticatedCall(myListener, "getrecentusermedia", dict);
- }
-
- function MultiGetter() {
- }
-
- MultiGetter.prototype = {
- mTimer: Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer),
- init: function(aSvc, aListener, aEnumerator) {
- this.mHasNew = false;
- this.mNeedSave = false;
- this.mSvc = aSvc;
- this.mListener = aListener;
- this.mArray = new Array();
- while (aEnumerator.hasMoreElements()) {
- var p = aEnumerator.getNext();
- p.QueryInterface(Components.interfaces.flockIPhotoPerson);
-
- this.mArray.push(p);
- }
- this.next();
- },
- finish: function() {
- //dump("FINITI\n");
- if (this.mHasNew) {
- this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_HAS_NEW);
- }
- else if (this.mNeedSave) {
- this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_NEED_SAVE);
- }
- else {
- this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_NO_CHANGE);
- }
- return;
- },
- updatePerson: function(aPerson, aPhoto) {
- //dump(aPerson.username + "updating person\n");
- var seq = aPerson.seq;
- var newSeq = parseInt(aPhoto.id);
- if (newSeq > seq) {
- var oldHasNew = aPerson.hasNew;
- aPerson.seq = aPhoto.id;
- this.mNeedSave = true;
- if (seq != 0) {
- this.mHasNew = true;
- aPerson.hasNew = true
- if (oldHasNew == false) {
- aPerson.lastNewSeq = seq + 1;
- }
- }
- }
- },
- notify: function() {
- this.doNext();
- },
- next: function() {
- this.mTimer.initWithCallback(this, 1000, 0);
- },
- doNext: function() {
- //dump("NEXT PLEASE\n");
- var inst = this;
-
- if (!this.mArray.length) {
- this.finish();
- return;
- }
- var person = this.mArray.pop();
-
- var listener = {
- onSearchResult: function(aEnumerator) {
- //dump("b search result\n");
- while (aEnumerator.hasMoreElements()) {
- var photo = aEnumerator.getNext();
- inst.updatePerson(person, photo);
- break;
- }
- inst.next();
- },
- onError: function(aError) {
- //dump("b search eror\n");
- inst.finish();
- }
- }
- this.mSvc.search(listener, person.id, "", "", 1, 1);
- }
- }
-
- photobucketService.prototype.getMostRecentPhotoForList =
- function photobucketService_getMostRecentPhotoForList(aListener, aEnumerator)
- {
- var mg = new MultiGetter();
- mg.init(this, aListener, aEnumerator);
- }
-
- photobucketService.prototype.supportsSearch =
- function photobucketService_supportsSearch( aQueryString ) {
-
- var aQuery = new queryHelper(aQueryString);
-
- if (aQuery.special) {
- var channel = this._channels["special:" + aQuery.special];
- if (channel) {
- return channel.supportsSearch;
- }
- }
-
- if (aQuery.user)
- return true;
- if (aQuery.search)
- return false;
- return null;
- }
-
-
- photobucketService.prototype.queryChannel =
- function photobucketService_queryChannel(aListener, aQueryString, aCount, aPage)
- {
- var aQuery = new queryHelper(aQueryString);
- var inst = this;
-
- var myListener = {
- onResult: function (aXML) {
- var rval = inst.handlePhotosResult(aXML);
- var enum_ = {
- hasMoreElements: function() {
- return (rval.length > 0);
- },
- getNext: function() {
- return rval.shift();
- }
- }
- aListener.onSearchResult(enum_);
- },
- onError: function (aError) {
- // if we get an error here this probably means user inputted an illegal character
- // do nothign and let the "Sorry, no results found" message appear
- }
- }
-
- var params = {
- page: aPage,
- num: aCount
- }
-
- if (aQuery.getKey('special') == 'recent') {
- var dict = params2Dictionary(params);
- this.api.call(myListener, "getrecentphotos", dict);
- }
-
- if (aQuery.hasKey('search')) {
- // don't pass in encoded text for PB
- // if an illegal char is used, we will return no results
- var aText = aQuery.search;
- if (aText && aText.length) {
- params.query = aText.split(".")[0];
- var dict = params2Dictionary(params);
- this.api.call(myListener, "search", dict);
- }
- }
- }
-
- photobucketService.prototype.search =
- function photobucketService_search(aListener, aQueryString, aCount, aPage)
- {
- var aQuery = new queryHelper(aQueryString);
- if (!aQuery.user) {
- this.queryChannel(aListener, aQueryString, aCount, aPage);
- return;
- }
- var aUserid = aQuery.user;
-
- var inst = this;
-
- var myListener = {
- onResult: function (aXML) {
- var rval = inst.handlePhotosResult(aXML);
- var enum_ = {
- hasMoreElements: function() {
- return (rval.length > 0);
- },
- getNext: function() {
- return rval.shift();
- }
- }
- aListener.onSearchResult(enum_);
- },
- onError: function (aError) {
- aListener.onError(aError);
- }
- }
-
- var params = {};
-
-
- if (aUserid) {
- params.username = aUserid;
- params.perpage = aCount;
- }
-
- if (aQuery.search) params.query = aQuery.getEncodedKey('search').split(".")[0];
- if (aPage) params.page = aPage;
- if (aQuery.album) params.album_name = aQuery.album;
-
- params.media = 'all';
-
- var dict = params2Dictionary(params);
- if (params.query != null) {
- this.api.call(myListener, "search", dict);
- } else if (params.username != null) {
- if (params.album_name) {
- this.api.authenticatedCall(myListener, "getuseralbumpaginated", dict);
- }else
- this.api.authenticatedCall(myListener, "getrecentusermedia", dict);
- }
-
- }
-
- photobucketService.prototype.createAlbum =
- function photobucketService_createAlbum(aListener, aPath)
- {
- var svc = this;
- this.logger.debug("createAlbum - aPath = "+aPath);
- var albumCreationListener = {
- onResult: function(aXML) {
- svc.logger.info(aPath + " album successfully created");
- var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
- .createInstance(flockIPhotoAlbum);
- var newAlbumPath;
- if (params.parent_album_name) {
- newAlbumPath = params.parent_album_name + params.new_album_name;
- } else {
- newAlbumPath = params.new_album_name;
- }
- newAlbum.title = newAlbumPath;
- newAlbum.id = newAlbumPath;
- aListener.onCreateAlbum(newAlbum);
- },
- onError: function(aError) {
- svc.logger.error("Error in album creation");
- aListener.onError(aError);
- }
- }
-
- var parentDir = "";
- var pathName = aPath.split('/');
- var params = new Object();
- params.new_album_name = pathName.pop();
- var dict;
-
- for (var i = 0; i < pathName.length; i++) {
- parentDir += pathName[i] + '/';
- }
-
- if (parentDir.length) {
- params.parent_album_name = parentDir;
- }
-
- dict = params2Dictionary(params);
- this.api.authenticatedCall(albumCreationListener, "createalbum", dict);
- }
-
- photobucketService.prototype.handleAlbumsResult =
- function photobucketService_handleAlbumsResult(aXML)
- {
- var rval = new Array();
- var albumList = aXML.getElementsByTagName("photoalbum");
- for (var i = 0; i < albumList.length; i++) {
- var album = albumList[i];
- var title = album.getAttribute("name");
-
- // the first album node has no name attr, so skip it
- if (!title) continue;
-
- var username = album.getAttribute('username');
- var id;
- // parse out the prefix /username/
- if (title.match(album.getAttribute('username')) && title != username) {
- id = title.substring(username.length + 1);
- var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
- .createInstance(flockIPhotoAlbum);
- newAlbum.id = id;
- newAlbum.title = id;
- rval.push(newAlbum);
- }
- }
- return rval;
- }
-
- photobucketService.prototype.getAccountStatus =
- function photobucketService_getAccountStatus(aListener)
- {
- var inst = this;
- var myListener = {
- onResult: function(aXML) {
- try {
- var result = Cc["@mozilla.org/hash-property-bag;1"]
- .createInstance(Ci.nsIWritablePropertyBag2);
- var username = aXML.getElementsByTagName("username")[0]
- .firstChild
- .nodeValue;
- var maxSpace = aXML.getElementsByTagName("megabytes_allowed")[0]
- .firstChild
- .nodeValue;
- var usedSpace = aXML.getElementsByTagName("megabytes_used")[0]
- .firstChild
- .nodeValue;
- var isPremium = aXML.getElementsByTagName("premium")[0]
- .firstChild
- .nodeValue;
- result.setPropertyAsAString("username", username);
- result.setPropertyAsAString("maxSpace", maxSpace);
- result.setPropertyAsAString("usedSpace", usedSpace);
- result.setPropertyAsAString("maxFileSize", "");
- result.setPropertyAsAString("usageUnits", "megabytes");
- result.setPropertyAsBool("isPremium", (isPremium == "1"));
- aListener.onSuccess(result, "");
- } catch (ex) {
- inst.logger.error('getaccountstatus error :' + ex);
- }
- },
- onError: function (aError) {
- aListener.onError(aError);
- }
- }
- var params = new Object();
- var dict = params2Dictionary(params);
- this.api.authenticatedCall(myListener, "getuserinfo", dict);
- }
-
- photobucketService.prototype.getAlbums =
- function photobucketService_getAlbums(aListener, aUsername)
- {
- var inst = this;
- var myListener = {
- onResult: function (aXML) {
- try {
- var rval = inst.handleAlbumsResult(aXML);
- var enum_ = {
- hasMoreElements: function() {
- return (rval.length > 0);
- },
- getNext: function() {
- return rval.shift();
- }
- }
- aListener.onGetAlbumsResult(enum_);
- } catch(e) {
- inst.logger.error(e);
- aListener.onError(null);
- }
- },
- onError: function (aXML) {
- aListener.onError(aXML);
- }
- }
- var params = new Object();
- params.recurse = "true";
- params.view = "flat"
- params.media = "none";
- if (aUsername) {
- params.username = aUsername;
- }
- var dict = params2Dictionary(params);
- this.api.authenticatedCall(myListener, "getuseralbum", dict);
- }
-
- photobucketService.prototype.mUploader = null;
- photobucketService.prototype.icon = PHOTOBUCKET_FAVICON;
-
- /* features for service */
- photobucketService.prototype.supportsFeature =
- function photobucketService_supportsFeature(aFeature)
- {
- var supports = {};
- supports.tags = false;
- supports.title = false;
- supports.contacts = false;
- supports.privacy = false;
- supports.fileName = true;
- supports.albumCreation = true;
- return (supports[aFeature] == true);
- }
-
- photobucketService.prototype.mSupportsTitle = false;
- photobucketService.prototype.mSupportsTags = false;
- photobucketService.prototype.mSupportsContacts = false;
- photobucketService.prototype.mSupportsPrivacey = false;
-
- photobucketService.prototype.init =
- function photobucketService_init()
- {
- if (this.initialized) return;
- this.initialized = true;
-
- DEBUG(".init()");
-
- this.prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
- if ( this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
- !this.prefService.getBoolPref(SERVICE_ENABLED_PREF) )
- {
- DEBUG("Pref "+SERVICE_ENABLED_PREF+" set to FALSE... not initializing.");
- var catMgr = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
- catMgr.deleteCategoryEntry("wsm-startup", CATEGORY_COMPONENT_NAME, true);
- catMgr.deleteCategoryEntry("flockWebService", CATEGORY_ENTRY_NAME, true);
- catMgr.deleteCategoryEntry("flockMediaProvider", CATEGORY_ENTRY_NAME, true);
- return;
- }
-
- this.mAuthUser = {};
-
- this.faves_coop = Components.classes["@flock.com/singleton;1"]
- .getService(Components.interfaces.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
-
- this.urn = 'urn:photobucket:service';
- this.pbService = new this.faves_coop.Service(
- this.urn,
- {
- name: "photobucket",
- desc: "The Photobucket Service",
- contactLabel: 'People'
- }
- );
- this.pbService.serviceId = PHOTOBUCKET_CONTRACTID;
- if (!gPhotobucketAPI) {
- gPhotobucketAPI = new PhotobucketAPI();
- }
- this.api = gPhotobucketAPI;
-
- // Load Web Detective file
- this.webDetective = this.acUtils.useWebDetective("photobucket.xml");
- for (var s in gStrings) {
- gStrings[s] = this.webDetective.getString("photobucket", s, gStrings[s]);
- }
- this.mApiUrl = gStrings["apiURL"];
- this.pbService.domains = gStrings["domains"];
- this.pbService.loginURL = gStrings["userloginURL"];
-
- // Update auth states
- try {
- if (this.webDetective.detectCookies("photobucket", "loggedout", null)) {
- this.acUtils.markAllAccountsAsLoggedOut(PHOTOBUCKET_CONTRACTID);
- this.mAuthUser = null;
- this.mUploader = null;
- } else {
- this.checkPersistedToken();
- }
- } catch (ex) {
- this.logger.error("ERROR updating auth states for Photobucket: "+ex);
- }
- }
-
- photobucketService.prototype.checkPersistedToken =
- function photobucketService_checkPersistedToken()
- {
- var acctURN = this.acUtils.getFirstAuthenticatedAccountForService(PHOTOBUCKET_CONTRACTID);
- if (!acctURN) { return; }
- var token = this.faves_coop.get(acctURN).authToken;
- if (token) {
- this.logger.debug('checking if the session associated with the token is still valid ... ' + token);
- // try to get the session from the persisted token
- var inst = this;
- var myListener = {
- onResult: function(aXML) {
- try {
- var resp = aXML.getElementsByTagName('response');
- if (resp[0].getAttribute('stat') == 'ok') {
- var username = aXML.getElementsByTagName('username')[0].firstChild.nodeValue;
- var sessionkey = aXML.getElementsByTagName('session_key')[0].firstChild.nodeValue;
- inst.api.mApiUrl = aXML.getElementsByTagName("url")[0].firstChild.nodeValue;
- inst.getAuthUser().id = username;
- inst.getAuthUser().username = username;
- inst.getAuthUser().fullname = username;
- inst.getAuthUser().sessionkey = sessionkey;
- if (!inst.api.mSessionRefreshTimer) inst.api.fireSessionRefreshTimer();
- } else {
- inst.mAuthUser = null;
- this.mUploader = null;
- }
- }
- catch(e) {
- inst.logger.error(e);
- }
- },
- onError: function(aErr) {
- return false;
- }
- }
- var params = {};
- params.service_token = token;
- inst.call(myListener, "getsession", params2Dictionary(params));
- }
- //this.mAuthUser.sessionkey = null;
- }
-
- photobucketService.prototype.getAuthState =
- function photobucketService_getAuthState()
- {
- return this.state;
- }
-
- photobucketService.prototype.__defineGetter__("supportsTitle", function () { return this.mSupportsTitle; })
- photobucketService.prototype.__defineGetter__("supportsTags", function () { return this.mSupportsTags; })
- photobucketService.prototype.__defineGetter__("supportsContacts", function () { return this.mSupportsContacts; })
- photobucketService.prototype.__defineGetter__("supportsPrivacey", function () { return this.mSupportsPrivacey; })
- photobucketService.prototype.__defineGetter__("authState", function () { return this.state; })
-
- photobucketService.prototype.logout =
- function photobucketService_logout()
- {
- this.mAuthUser = null;
- this.mUploader = null;
- if (this.mSessionRefreshTimer) { this.mSessionRefreshTimer.cancel(); }
- this.acUtils.removeCookies(this.webDetective.getSessionCookies("photobucket"));
- }
-
-
- photobucketService.prototype.getAuthUser =
- function photobucketService_getAuthUser()
- {
- return this.api.mAuthUser;
- }
-
- photobucketService.prototype.getAuthPerson =
- function photobucketService_getAuthPerson()
- {
- var user = this.getAuthUser();
- if (!user) {
- return null;
- }
- var person = {};
- person.id = user.id;
- person.fullname = user.fullname;
- person.username = user.username;
- person.service = this;
- return person;
- }
-
-
- photobucketService.prototype.notify = function photobucketService_sessionTimerNotify(aTimer) {
- var inst = this;
- var sessionRefreshListener = {
- onAuth: function() {
- inst.logger.debug('yay! pbucket refreshed its session key with the timer');
- },
-
- onError: function(aError) {
- inst.logger.error('!!!boo! error refreshing session key on the timer');
- }
- }
- this.getSessionKey(sessionRefreshListener);
- }
-
-
- photobucketService.prototype.getSessionKey =
- function photobucketService_getSessionKey(aListener)
- {
- var acctURN = this.acUtils.getFirstAuthenticatedAccountForService(PHOTOBUCKET_CONTRACTID);
- if (!acctURN) aListener.onError(null);
- var token = this.faves_coop.get(acctURN).token;
- this.logger.debug(">>>getSessionKey called with the token "+token+"\n\n\n");
-
- var inst = this;
- var mySessionListener = {
- onResult: function(aXML) {
- var username = aXML.getElementsByTagName('username')[0].firstChild.nodeValue;
- var sessionkey = aXML.getElementsByTagName('session_key')[0].firstChild.nodeValue;
- inst.api.mApiUrl = aXML.getElementsByTagName('url')[0].firstChild.nodeValue;
- inst.getAuthUser().id = username;
- inst.getAuthUser().username = username;
- inst.getAuthUser().fullname = username;
- inst.getAuthUser().sessionkey = sessionkey;
- aListener.onAuth();
- },
- onError: function(aErr) {
- inst.logger.debug('>>>>>> ' + aErr.errorString + '\n\n')
- aListener.onError(aErr);
- }
- };
- var params = {};
- params.service_token = token;
- inst.call(mySessionListener, "getsession", params2Dictionary(params));
- }
-
- photobucketService.prototype.upload =
- function photobucketService_upload(aListener, aUpload, aFile)
- {
- var inst = this;
- var sigParams = {};
- var myParams = {};
-
- this.logger.debug('uploading to album ' + aUpload.album);
- myParams.version = PHOTOBUCKET_API_VERSION;
- myParams.scid = PHOTOBUCKET_SCID;
- myParams.method = 'upload';
- myParams.description = aUpload.description;
- myParams.title = aUpload.title;
- myParams.album_name = aUpload.album;
- myParams.session_key = this.getAuthUser().sessionkey;
- myParams.sig = this.api.buildSig("upload", sigParams, true);
-
- sigParams.session_key = this.getAuthUser().sessionkey;
-
- this.mUploader = new PhotoUploader();
- this.mUploader.setEndpoint(inst.api.mApiUrl);
- this.mUploader.photoParam = "uploadfile";
-
- var myListener = {
- onResult: function(aXML) {
- var photo = aXML.getElementsByTagName("photo")[0];
- if (photo) {
- inst.logger.debug('uploaded the pic named ' + photo.getAttribute('name'));
- var rval = inst.handlePhotosResult(aXML);
- aListener.onUploadComplete(aUpload);
- aListener.onUploadFinalized(aUpload, rval[0]);
- }
- else {
- aListener.onError(inst.api.getError("SERVICE_ERROR", aXML, null));
- }
- },
- onError: function(aErrorCode) {
- if (aErrorCode) {
- aListener.onError(inst.api.getError("HTTP_ERROR", null, aErrorCode));
- } else {
- aListener.onError(inst.api.getError("SERVICE_ERROR", null, null));
- }
- },
- onProgress: function(aCurrentProgress) {
- aListener.onProgress(aCurrentProgress);
- }
- }
- this.mUploader.upload(myListener, aFile, myParams, aUpload);
- }
-
- photobucketService.prototype.cancelUpload =
- function photobucketService_cancelUpload()
- {
- try {
- this.mUploader.req.abort();
- } catch(e) { }
- }
-
-
- // flockIPollingService implementation
-
- photobucketService.prototype.refresh =
- function photobucketService_refresh(aURN, aListener)
- {
- var refreshItem = this.faves_coop.get(aURN);
- if (refreshItem.isInstanceOf(this.faves_coop.Account)) {
- aListener.onResult();
- }
- }
-
-
- photobucketService.prototype.migrateAccount =
- function photobucketService_migrateAccount( aId, aUsername) {
- this.init();
-
- var token = '';
- try {
- token = flock_getCharPref(PHOTOBUCKET_TOKEN_PREF);
- } catch (e) { }
-
- this.addAccountById(aId, false, null, aUsername, token);
- }
-
- // BEGIN flockIWebService interface
- photobucketService.prototype.addAccountById =
- function photobucketService_addAccountById(aAccountID, aIsTransient, aListener, aUsername, aToken)
- {
- this.logger.debug("{flockIWebService}.addAccountById('"+aAccountID+"', "+aIsTransient+", aListener)");
-
- if (!aUsername) {
- // Get the password associated with this account
- var pw = this.acUtils.getPassword(this.urn+':'+aAccountID);
- var name = pw.user;
- var token = '';
- var pollable = false;
- var auth = false;
- } else {
- var name = aUsername;
- var token = aToken;
- var pollable = true;
- var auth = true;
- }
-
- var accountURN = "urn:flock:photobucket:"+aAccountID;
- var acctCoopObj = this.faves_coop.get(accountURN);
- if (!acctCoopObj) {
- acctCoopObj = new this.faves_coop.Account(
- accountURN,
- {
- accountId: aAccountID,
- name: name, // This gets changed to the user's full name once logged in
- serviceId: PHOTOBUCKET_CONTRACTID,
- service: this.pbService,
- URL: "http://www.photobucket.com/",
- favicon: this.icon,
- isTransient: aIsTransient,
- isPollable: pollable,
- authToken: token,
- isAuthenticated: auth
- }
- );
- this.faves_coop.accounts_root.children.add(acctCoopObj);
- }
-
- // perhaps we should do a checktoken and if valid go ahead and set the account as logged in?
-
- var acct = this.getAccount(acctCoopObj.id());
- if (aListener) aListener.onSuccess(acct, "addAccount");
- return acct;
- }
- // END flockIWebService interface
-
-
- // BEGIN flockIAuthenticateNewAccount interface
- photobucketService.prototype.authenticateNewAccount =
- function photobucketService_authenticateNewAccount(aListener)
- {
- this.logger.debug("{flockIAuthenticateNewAccount}.authenticateNewAccount(aListener)");
- aListener.onStart(null, "newaccountstarted");
- var inst = this;
- var tokenListener = {
- onResult: function (aXML) {
- inst.logger.debug(".authenticateNewAccount(): tokenListener: onResult()");
- var params = {
- service_token: aXML.getElementsByTagName("service_token")[0].firstChild.nodeValue
- };
- var sessionListener = {
- onResult: function (aXML) {
- inst.logger.debug(".authenticateNewAccount(): tokenListener: sessionListener: onResult()");
- var username = aXML.getElementsByTagName("username")[0].firstChild.nodeValue;
- var sessionkey = aXML.getElementsByTagName("session_key")[0].firstChild.nodeValue;
- inst.api.mApiUrl = aXML.getElementsByTagName("url")[0].firstChild.nodeValue;
- inst.getAuthUser().id = username;
- inst.getAuthUser().username = username;
- inst.getAuthUser().fullname = username;
- inst.getAuthUser().sessionkey = sessionkey;
- var acctURN = inst.acUtils.getFirstAuthenticatedAccountForService(PHOTOBUCKET_CONTRACTID);
- var account = null;
- try {
- account = inst.getAccount(acctURN);
- if (!account) throw "ACCOUNT WAS NOT CREATED";
- } catch (ex) {
- dump(ex);
- inst.logger.error(".authenticateNewAccount(): tokenListener: onResult(): ERROR: account was not created");
- if (aListener) {
- aListener.onError(null, "newaccount", null);
- }
- return;
- }
- if (aListener) {
- aListener.onSuccess(account, "newaccount");
- }
- },
- onError: function (aError) {
- inst.logger.debug(".authenticateNewAccount(): tokenListener: sessionListener: onError()");
- inst.logger.debug(">>>>>> " + aError.errorString);
- if (aListener) {
- aListener.onError(aError, "newaccount", aError);
- }
- }
- };
- var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Components.interfaces.nsIWindowMediator);
- var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
- .getService(Components.interfaces.nsIWindowWatcher);
- var topWin = wm.getMostRecentWindow(null);
- var loginUrl = inst.api.buildUrl(gStrings["serviceloginURL"], "login", params);
- var url = "chrome://browser/content/flock/photo/photoLoginWindow.xul?"
- + "url="+escape(loginUrl)
- + "&finalString="+escape("You have granted");
- var chrome = "chrome,close,titlebar,resizable=yes,toolbar,dialog=no,"
- + "scrollbars=yes,modal,centerscreen";
- topWin.open(url, "_blank", chrome);
- // Wait till the window closes
- inst.api.call(sessionListener, "getsession", params2Dictionary(params));
- },
- onError: function (aError) {
- inst.logger.debug(".authenticateNewAccount(): tokenListener: onError()");
- inst.logger.debug(">>>>>> " + aError.errorString);
- if (aListener) {
- aListener.onError(aError, "newaccount");
- }
- }
- };
- if (!this.api.mAuthUser) {
- this.api.mAuthUser = {};
- }
- this.api.getToken(tokenListener);
- }
- // END flockIAuthenticateNewAccount interface
-
-
- // BEGIN flockIManageableWebService interface
- photobucketService.prototype.getAccountIDFromDocument =
- function photobucketService_getAccountIDFromDocument(aDocument)
- {
- this.logger.debug("{flockIManageableWebService}.getAccountIDFromDocument(aDocument)");
- aDocument.QueryInterface(Components.interfaces.nsIDOMHTMLDocument);
- var results = Components.classes["@mozilla.org/hash-property-bag;1"]
- .createInstance(Components.interfaces.nsIWritablePropertyBag2);
- if (this.webDetective.detect("photobucket", "accountinfo", aDocument, results)) {
- return results.getPropertyAsAString("userid");
- } else {
- // We could not detect any account info on the login landing page. This
- // may mean that it's the API authentication login landing page, which
- // doesn't have any account info. If this is the case, then we should
- // have a temp password entry associated with the session cookie.
- var sessionValue = this.acUtils.getCookie("http://photobucket.com", "PHPSESSID");
- var pw = this.acUtils.getTempPassword("photobucket:session:"+sessionValue);
- if (pw) {
- this.logger.debug("Sneaky! Got acctID from a temp password associated with session cookie!");
- return pw.user;
- }
- }
- return null;
- }
-
- photobucketService.prototype.getCredentialsFromForm =
- function photobucketService_getCredentialsFromForm(aForm)
- {
- var inst = this;
- var detectForm = function (aType, aResults) {
- return inst.webDetective.detectForm("photobucket", aType, aForm, aResults);
- };
-
- var formType = "login";
- var results = getCompTK().newResults();
- if (!detectForm(formType, results)) {
- formType = "signup";
- results = getCompTK().newResults();
- if (!detectForm(formType, results)) {
- formType = "changepassword";
- results = getCompTK().newResults();
- if (!detectForm(formType, results)) {
- results = null;
- }
- }
- }
-
- if (results) {
- var pw = {
- QueryInterface: function(aIID) {
- if (!aIID.equals(Components.interfaces.nsISupports) &&
- !aIID.equals(Components.interfaces.nsIPassword) &&
- !aIID.equals(Components.interfaces.flockIPassword)) {
- throw Components.interfaces.NS_ERROR_NO_INTERFACE;
- }
- return this;
- },
- user: results.getPropertyAsAString("username"),
- password: results.getPropertyAsAString("password"),
- host: null,
- formType: formType
- };
-
- // Doing a bit of a hack here...
- // Since the Photobucket login landing page doesn't always reveal which
- // account is logged in, we will need to look at the session cookie and
- // see if its the same as what it was when the user last logged in. So
- // at this point we're just storing the account username as a temp
- // password entry associated with the session cookie token.
- var sessionValue = this.acUtils.getCookie("http://photobucket.com", "PHPSESSID");
- this.acUtils.clearTempPassword("photobucket:session:"+sessionValue);
- this.acUtils.setTempPassword("photobucket:session:"+sessionValue, pw.user, "", formType);
- return pw;
- }
- return null;
- }
-
- photobucketService.prototype.updateAccountStatusFromDocument =
- function photobucketService_updateAccountStatusFromDocument(aDocument)
- {
- var inst = this;
- this.logger.debug("{flockIManageableWebService}.updateAccountStatusFromDocument('"+aDocument.URL+"')");
- if (this.webDetective.detect("photobucket", "loggedout", aDocument, null)) {
- this.acUtils.markAllAccountsAsLoggedOut(PHOTOBUCKET_CONTRACTID);
- this.logout();
- } else if (this.webDetective.detect("photobucket", "loggedin", aDocument, null)) {
- var acctID;
- var results = Components.classes["@mozilla.org/hash-property-bag;1"]
- .createInstance(Components.interfaces.nsIWritablePropertyBag2);
- if (this.webDetective.detect("photobucket", "accountinfo", aDocument, results)) {
- acctID = results.getPropertyAsAString("userid");
- } else {
- // We could not detect any account info on the login landing page. This
- // may mean that it's the API authentication login landing page, which
- // doesn't have any account info. If this is the case, then we should
- // have a temp password entry associated with the session cookie.
- var sessionValue = this.acUtils.getCookie("http://photobucket.com", "PHPSESSID");
- var pw = this.acUtils.getTempPassword("photobucket:session:"+sessionValue);
- if (pw) {
- this.logger.debug("Sneaky! Got acctID from a temp password associated with session cookie!");
- acctID = pw.user;
- }
- }
- if (acctID) {
- var acctURN = this.acUtils.getAccountURNById(this.urn, acctID);
- if (acctURN) {
- var acctCoopObj = this.faves_coop.get(acctURN);
- if (!acctCoopObj.isAuthenticated) {
- // Re-authenticate the API
- var reauthListener = {
- onAuth: function () {
- inst.logger.debug("reauthListener: onAuth()");
- },
- onError: function (aError) {
- inst.logger.debug("reauthListener: onError()");
- acctCoopObj.isAuthenticated = false;
- }
- };
- this.getAccount(acctURN).login(reauthListener);
- // Prematurely set isAuthenticated to TRUE in order to avoid other
- // asyncronous auth attempts before this one completes.
- acctCoopObj.isAuthenticated = true;
- }
- }
- }
- }
- }
- // END flockIManageableWebService interface
-
-
- // BEGIN flockIMediaWebService interface
- photobucketService.prototype.decorateForMedia =
- function photobucketService_decorateForMedia(aDocument)
- {
- this.logger.debug("{flockIMediaWebService}.decorateForMedia(aDocument)");
- var results = Components.classes["@mozilla.org/hash-property-bag;1"]
- .createInstance(Components.interfaces.nsIWritablePropertyBag2);
- if (this.webDetective.detect("photobucket", "media", aDocument, results)) {
- var userid = results.getPropertyAsAString("userid");
- var mediaArr = new Array();
-
- if (!aDocument._flock_decorations) {
- aDocument._flock_decorations = new Object();
- }
- var media = {
- name: userid,
- query: 'user:' + userid + "|username:" + userid,
- label: userid,
- favicon: this.icon,
- service: this.shortName
- }
- mediaArr.push(media);
-
- aDocument._flock_decorations.mediaArr = mediaArr;
- this.obs.notifyObservers(aDocument, 'media', 'media:update');
- }
- }
-
- photobucketService.prototype.handlesMediaStream =
- function photobucketService_handlesMediaStream()
- {
- return true;
- }
-
- photobucketService.prototype.checkIsStreamUrl =
- function photobucketService_checkIsStreamUrl(aUrl)
- {
- // Videos:
- // /player.swf?file=http://vid166.photobucket.com/albums/u113/h671226/Smart_Dog.flv
- // Images:
- // http://i166.photobucket.com/albums/u105/such-a-craka/thfhg.jpg
- if (this.webDetective.detectNoDOM("photobucket", "isStreamUrl", "", aUrl, null)) {
- this.logger.debug("Checking if url is photobucket stream: YES: " + aUrl);
- return true;
- }
- this.logger.debug("Checking if url is photobucket stream: NO: " + aUrl);
- return false;
- }
-
- photobucketService.prototype.getMediaQueryFromURL =
- function photobucketService_getMediaQueryFromURL(aUrl, aListener)
- {
- var userName = null;
- var detectResults = Cc["@mozilla.org/hash-property-bag;1"]
- .createInstance(Ci.nsIWritablePropertyBag2);
- if (this.webDetective.detectNoDOM("photobucket", "person", "", aUrl, detectResults)) {
- userName = detectResults.getPropertyAsAString("userid");
- }
-
- if (userName) {
- var results = Components.classes["@mozilla.org/hash-property-bag;1"]
- .createInstance(Components.interfaces.nsIWritablePropertyBag2);
- results.setPropertyAsAString("query", "user:" + userName + "|username:" + userName);
- results.setPropertyAsAString("title", this.title + " user: " + userName);
- aListener.onSuccess(results, "query");
- } else {
- aListener.onError(null, "Unable to get user.", null);
- }
- }
- // END flockIMediaWebService interface
-
-
- photobucketService.prototype.doMigration =
- function photobucketService_doMigration(aDatasource, aAccountURN) {
- }
-
-
- // ================================================
- // ========== BEGIN XPCOM Module support ==========
- // ================================================
-
- function createModule(aParams) {
- return {
- registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
- aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
- aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
- aParams.contractID, aFileSpec,
- aLocation, aType );
- var catMgr = Cc["@mozilla.org/categorymanager;1"]
- .getService(Ci.nsICategoryManager);
- if (!aParams.categories) { aParams.categories = []; }
- for (var i = 0; i < aParams.categories.length; i++) {
- var cat = aParams.categories[i];
- catMgr.addCategoryEntry( cat.category, cat.entry,
- cat.value, true, true );
- }
- },
- getClassObject: function (aCompMgr, aCID, aIID) {
- if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
- if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
- return { // Factory
- createInstance: function (aOuter, aIID) {
- if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
- var comp = new aParams.componentClass();
- if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
- return comp.QueryInterface(aIID);
- }
- };
- },
- canUnload: function (aCompMgr) { return true; }
- };
- }
-
- // NS Module entrypoint
- function NSGetModule(aCompMgr, aFileSpec) {
- return createModule({
- componentClass: photobucketService,
- CID: PHOTOBUCKET_CID,
- contractID: PHOTOBUCKET_CONTRACTID,
- componentName: CATEGORY_COMPONENT_NAME,
- implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); },
- categories: [
- { category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: PHOTOBUCKET_CONTRACTID },
- { category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: PHOTOBUCKET_CONTRACTID },
- { category: "flockMediaProvider", entry: CATEGORY_ENTRY_NAME, value: PHOTOBUCKET_CONTRACTID }
- ]
- });
- }
-
- // ========== END XPCOM Module support ==========
-
-
- // ====================================================
- // ============= BEGIN photobucket API ================
- // ====================================================
-
- function PhotobucketAPI() {
- this._logger = Cc["@flock.com/logger;1"]
- .createInstance(Ci.flockILogger);
- this._logger.init("photobucketAPI");
- this._logger.info("Created Photobucket API Object");
- this.acUtils = Cc["@flock.com/account-utils;1"]
- .getService(Ci.flockIAccountUtils);
- this.webDetective = this.acUtils.useWebDetective("photobucket.xml");
- this.faves_coop = Cc["@flock.com/singleton;1"]
- .getService(Ci.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
-
- this.mApiUrl = gStrings["apiURL"];
- this.mAuthUser = null;
- this.mSessionRefreshTimer = null;
- var inst = this;
- };
-
-
- PhotobucketAPI.prototype.isLoggedIn =
- function photobucketAPI_isLoggedIn() {
- return (this.mAuthUser && this.mAuthUser.sessionkey != null);
- };
-
-
- PhotobucketAPI.prototype.getToken =
- function photobucketAPI_getToken(aListener) {
- var inst = this;
- var tokenListener = {
- onResult: function (aXML) {
- try {
- var resp = aXML.getElementsByTagName("response");
- if (resp[0].getAttribute("stat") == "ok") {
- //rval = resp[0].firstChild.nodeValue;
- aListener.onResult(aXML);
- } else {
- aListener.onError(null); //TODO - figure out errors
- //rval = -1;
- }
- }
- catch(e) {
- inst._logger.error(e);
- }
- },
- onError: function (aError) {
- inst._logger.error(aError.errorString);
- aListener.onError(aError);
- }
- }
- var params = {};
- this.call(tokenListener, "getservicetoken", params2Dictionary(params));
- };
-
-
- PhotobucketAPI.prototype.call =
- function photobucketAPI_call(aListener,
- aMethod,
- aDictionary,
- aAuth) {
- var inst = this;
- var params = this.dictionary2Params(aDictionary);
- var url = this.buildUrl(inst.mApiUrl, aMethod, params, aAuth);
- this._logger.debug(url + " < call");
- this.req = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
- .createInstance(Ci.nsIXMLHttpRequest)
- .QueryInterface(Ci.nsIJSXMLHttpRequest);
-
- this.req.open("GET", url, true);
- var req = this.req;
- this.req.onreadystatechange = function (aEvt) {
- if (req.readyState == 4) {
- try {
- inst._logger.debug("doCall[onreadystatechange] req.status = "
- + req.status);
- if (req.status/100 == 2) {
- inst._logger.debug(req.responseText);
- var rsp = req.responseXML.getElementsByTagName("response")[0];
- var stat = rsp.getAttribute("stat");
- if (stat != "ok") {
- aListener.onError(inst.getError("SERVICE_ERROR",
- req.responseXML,
- null));
- } else {
- aListener.onResult(req.responseXML);
- }
- } else {
- aListener.onError(inst.getError("HTTP_ERROR", null, req.status));
- }
- } catch(e) {
- inst._logger.error(e);
- // We need to convert to a string because that's what getError expects
- var errorCode = String(Ci.flockIError.XML_HTTP_REQUEST_ERROR)
- aListener.onError(inst.getError("HTTP_ERROR", null, errorCode));
- }
- }
- }
- this.req.send(null);
- };
-
-
- PhotobucketAPI.prototype.dictionary2Params =
- function photobucketAPI_dictionary2Params(aDictionary) {
- var params = {};
- var obj = {};
- var count = {};
- var keys = aDictionary.getKeys(count, obj);
- for (var i = 0; i < keys.length; ++i) {
- var supports = aDictionary.getValue(keys[i]);
- var supportsString = supports.QueryInterface(Ci.nsISupportsString);
- var val = supportsString.toString();
- params[keys[i]] = val;
- }
- return params;
- };
-
- PhotobucketAPI.prototype.authenticatedCall =
- function photobucketAPI_authenticatedCall(aListener,
- aMethod,
- aDictionary) {
- this._logger.debug("authenticatedCall " + aMethod);
- if (!this.isLoggedIn()) {
- this._logger.debug("not logged in, so trying unauth call for " + aMethod);
- return this.call(aListener, aMethod, aDictionary);
- }
- this._logger.debug("+++++" + this.mAuthUser.sessionkey);
- return this.call(aListener, aMethod, aDictionary, true);
- };
-
- PhotobucketAPI.prototype.doLogin =
- function photobucketAPI_doLogin(aAccountURN, aListener) {
- this._logger.debug(".doLogin('" + aAccountURN + "')");
- var inst = this;
- var tokenListener = {
- onResult: function(aXML) {
- inst._logger.debug(".doLogin('"
- + aAccountURN +
- "'): tokenListener: onResult()");
- // Time to authenticate...
- var params = {
- service_token: aXML.getElementsByTagName("service_token")[0]
- .firstChild
- .nodeValue
- };
- // persist the token
- var acctCoopObj = inst.faves_coop.get(aAccountURN);
- acctCoopObj.authToken = params.service_token;
-
- // listener for the upcoming "getsession" api call
- var sessionListener = {
- onResult: function(aXML) {
- inst._logger.debug(".doLogin('"
- + aAccountURN
- + "'): tokenListener:"
- + "sessionListener: onResult()");
- var username = aXML.getElementsByTagName('username')[0]
- .firstChild
- .nodeValue;
- var sessionkey = aXML.getElementsByTagName('session_key')[0]
- .firstChild
- .nodeValue;
- inst.mApiUrl = aXML.getElementsByTagName('url')[0]
- .firstChild
- .nodeValue;
- inst.mAuthUser.id = username;
- inst.mAuthUser.username = username;
- inst.mAuthUser.fullname = username;
- inst.mAuthUser.sessionkey = sessionkey;
- inst.acUtils.ensureOnlyAuthenticatedAccount(aAccountURN);
- if (!inst.mSessionRefreshTimer) inst.fireSessionRefreshTimer();
- aListener.onSuccess(null, "");
- },
- onError: function(aErr) {
- inst._logger.error(".doLogin('"
- + aAccountURN
- + "'): tokenListener: sessionListener: onError()");
- inst._logger.error(">>>>>> " + aErr.errorString);
- aListener.onError(aErr);
- }
- };
-
- // If we have the user's un/pw, then we can do this silently...
- var pw = inst.acUtils.getPassword("urn:photobucket:service:"
- + acctCoopObj.accountId);
- if (pw) {
- inst._logger.debug(".doLogin('"
- + aAccountURN
- + "'): tokenListener: onResult(): found password");
-
- var postBody = "action=login"
- + "&service_token="+params.service_token
- + "&sig="+inst.buildSig("login", params)
- + "&scid="+PHOTOBUCKET_SCID
- + "&method=login"
- + "&callback_verify="
- + "&username="+pw.user
- + "&password="+pw.password
- + "&login=Login";
- var hr = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
- .createInstance(Ci.nsIXMLHttpRequest)
- .QueryInterface(Ci.nsIJSXMLHttpRequest);
-
- var onReadyStateFunc = function(eEvt) {
- if (hr.readyState == 4) {
- inst._logger.debug(".doLogin('"
- + aAccountURN
- + "'): tokenListener:"
- + "onResult(): hr.onreadystatechange()");
- var results = Cc["@mozilla.org/hash-property-bag;1"]
- .createInstance(Ci.nsIWritablePropertyBag2);
- if (inst.webDetective.detectNoDOM("photobucket",
- "apiauth",
- "",
- hr.responseText,
- results)) {
- var hr2 = Cc['@mozilla.org/xmlextras/xmlhttprequest;1']
- .createInstance(Ci.nsIXMLHttpRequest)
- .QueryInterface(Ci.nsIJSXMLHttpRequest);
-
- hr2.onreadystatechange = function(eEvt2) {
- if (hr2.readyState == 4) {
- inst.call(sessionListener,
- "getsession",
- params2Dictionary(params));
- }
- }
-
- var postBody2 = "action=complete"
- + "&authorized=yes"
- + "&service_token=" + params.service_token
- + "&sig=" + inst.buildSig("login", params)
- + "&scid=" + PHOTOBUCKET_SCID
- + "&method=login"
- + "&callback_verify="
- + "&user_id="
- + results.getPropertyAsAString("user_id");
-
- hr2.backgroundRequest = true;
- hr2.open("POST", gStrings["serviceloginURL"],true);
- hr2.setRequestHeader("Content-Type",
- "application/x-www-form-urlencoded");
- hr2.send(postBody2);
- } else {
- inst.call(sessionListener,
- "getsession",
- params2Dictionary(params));
- }
- }
- };
-
- hr.onreadystatechange = onReadyStateFunc;
- hr.backgroundRequest = true;
- hr.open("POST", gStrings["serviceloginURL"],true);
- hr.setRequestHeader("Content-Type",
- "application/x-www-form-urlencoded");
- hr.send(postBody);
-
- } else {
- inst._logger.debug(".doLogin('"
- + aAccountURN +
- "'): tokenListener: onResult(): NO password!");
-
- // No password stored, so we have to prompt the user
- var windowManager = Cc["@mozilla.org/appshell/window-mediator;1"]
- .getService(Ci.nsIWindowMediator);
- var topWindow = windowManager.getMostRecentWindow(null);
-
- var loginUrl = inst.buildUrl(gStrings["serviceloginURL"],
- "login",
- params);
- var url = "chrome://browser/content/flock/photo/photoLoginWindow.xul?"
- + "url=" + escape(loginUrl)
- + "&finalString=" + escape("You have granted");
- var options = "chrome,"
- + "close,"
- + "titlebar,"
- + "resizable=yes,"
- + "toolbar,"
- + "dialog=no,"
- + "scrollbars=yes,"
- + "modal,"
- + "centerscreen";
- topWindow.open(url, "_blank", options);
- // we are waiting till window closes
-
- inst.call(sessionListener, "getsession", params2Dictionary(params));
- }
- },
- onError: function(aErr) {
- inst._logger.error(".doLogin('"
- + aAccountURN
- + "'): tokenListener: onError()");
- aListener.onError(aErr);
- }
- }
-
- if (!this.mAuthUser) {
- this.mAuthUser = {};
- }
- this.getToken(tokenListener);
- };
-
- PhotobucketAPI.prototype.fireSessionRefreshTimer =
- function photobucketAPI_fireSessionRefreshTimer() {
- this.mSessionRefreshTimer = Cc["@mozilla.org/timer;1"]
- .createInstance(Ci.nsITimer);
- // refresh the session key once an hour, probably can adjust this
- this.mSessionRefreshTimer.initWithCallback(this,
- PHOTOBUCKET_SESSION_REFRESH_INTERVAL,
- 2);
- };
-
- PhotobucketAPI.prototype.getError =
- function photobucketAPI_getError(aErrorType, aXML, aHTTPErrorCode) {
- var errorNode;
- var code;
- var serverErrorMessage;
- var error = Cc[FLOCK_ERROR_CONTRACTID]
- .createInstance(flockIError);
-
- this._logger.debug("getError aErrorType="
- + aErrorType
- + "; aHTTPErrorCode="
- + aHTTPErrorCode);
-
- if (aErrorType == "HTTP_ERROR") {
- error.errorCode = aHTTPErrorCode;
- return error;
- } else if (aErrorType == "SERVICE_ERROR") {
- try {
- errorNode = aXML.getElementsByTagName("error")[0];
- code = errorNode.getAttribute("code");
- serverErrorMessage = errorNode.getAttribute("msg");
- error.serviceErrorCode = code;
- error.serviceErrorString = serverErrorMessage;
- this._logger.debug("Found error code = "
- + code
- + " and message = '"
- + serverErrorMessage
- + "'");
- } catch (ex) {
- code = "-1"
- }
-
- if (!code) code = "-1";
-
- switch (code) {
- case "-1":
- error.errorCode = error.PHOTOSERVICE_INVALID_RESPONSE;
- break;
- case "007":
- case "008":
- error.errorCode = error.PHOTOSERVICE_LOGIN_FAILED;
- break;
- case "012":
- error.errorCode = error.PHOTOSERVICE_SESSION_KEY_EXPIRED;
- break;
- case "101":
- error.errorCode = error.PHOTOSERVICE_EMPTY_ALBUMNAME;
- break;
- case "102":
- error.errorCode = error.PHOTOSERVICE_INVALID_USER;
- break;
- case "103":
- error.errorCode = error.PHOTOSERVICE_INVALID_SEARCH_QUERY;
- break;
- case "104":
- error.errorCode = error.PHOTOSERVICE_INVALID_SEARCH_QUERY;
- break;
- case "105":
- error.errorCode = error.PHOTOSERVICE_INVALID_UPLOAD_FILE;
- break;
- case "106":
- error.errorCode = error.PHOTOSERVICE_INVALID_SEARCH_QUERY;
- break;
- case "107":
- error.errorCode = error.PHOTOSERVICE_INVALID_ALBUM;
- break;
- case "108":
- error.errorCode = error.PHOTOSERVICE_PRIVATE_ALBUM;
- break;
- case "109":
- error.errorCode = error.PHOTOSERVICE_PHOTOS_IN_ALBUM_LIMIT_REACHED;
- break;
- case "110":
- error.errorCode = error.PHOTOSERVICE_NO_FILE_UPLOADED;
- break;
- case "111":
- error.errorCode = error.PHOTOSERVICE_ALBUM_IS_OVER_SIZE_LIMIT;
- break;
- case "112":
- error.errorCode = error.PHOTOSERVICE_INVALID_UPLOAD_FILE;
- break;
- case "113":
- error.errorCode = error.PHOTOSERVICE_DUPLICATE_FILENAME;
- break;
- case "115":
- error.errorCode = error.PHOTOSERVICE_INVALID_ALBUMNAME;
- break;
- case "116":
- error.errorCode = error.PHOTOSERVICE_DUPLICATE_ALBUMNAME;
- break;
- case "314":
- error.errorCode = error.PHOTOSERVICE_FILE_IS_OVER_SIZE_LIMIT;
- break;
- default:
- error.errorCode = error.PHOTOSERVICE_UNKNOWN_ERROR;
- if (serverErrorMessage && serverErrorMessage.length) {
- error.serviceErrorString = serverErrorMessage;
- }
- break;
- }
- return error;
- }
- return null;
- };
-
- PhotobucketAPI.prototype.buildUrl =
- function photobucketAPI_buildUrl(aUrl, aMethod, aParams, aAuth) {
- var qs = "";
- var strConcat = "";
- for (var p in aParams) {
- qs += "&" + escape(p) + "=" + escape(aParams[p]);
- strConcat += escape(aParams[p]);
- }
- var rval = aUrl
- + "?method=" + aMethod
- + "&version=" + PHOTOBUCKET_API_VERSION;
- if (aAuth) {
- rval += "&session_key=" + this.mAuthUser.sessionkey;
- }
- rval += "&scid=" + PHOTOBUCKET_SCID
- + qs
- + "&sig=" + this.buildSig(aMethod, aParams, aAuth);
- this._logger.debug("this is your buildUrl: " + rval + "\n");
- return rval;
- };
-
- PhotobucketAPI.prototype.buildSig =
- function photobucketAPI_buildSig(aMethod, aParams, aAuth) {
- var qs = "";
- var strConcat = "";
- for (var p in aParams) {
- qs += "&" + escape(p) + "=" + escape(aParams[p]);
- if (p == 'service_token') {
- strConcat += escape(aParams[p]);
- }
- }
-
- this._logger.debug(strConcat + "<<<<<<<<strconcat\n");
- var preHash = aMethod
- + PHOTOBUCKET_PK
- + PHOTOBUCKET_SCID
- + strConcat
- + (aAuth ? this.mAuthUser.sessionkey : "");
- this._logger.debug("going to sig::: " + preHash);
-
- var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
- .createInstance(Ci.nsIScriptableUnicodeConverter);
- converter.charset = "UTF-8";
-
- var inputStream = converter.convertToInputStream(preHash);
- return FlockCryptoHash.md5Stream(inputStream);
- };
-
- // ========== END PhotobucketAPI class ==========
-
-
-
- // ====================================================
- // ========== BEGIN photobucketAccount class ==========
- // ====================================================
-
- function photobucketAccount()
- {
- this.acUtils = Components.classes["@flock.com/account-utils;1"]
- .getService(Ci.flockIAccountUtils);
- this.service = Cc[PHOTOBUCKET_CONTRACTID]
- .getService(Ci.flockIMediaWebService);
- this._coop = Components.classes["@flock.com/singleton;1"]
- .getService(Ci.flockISingleton)
- .getSingleton("chrome://flock/content/common/load-faves-coop.js")
- .wrappedJSObject;
- this.logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
- this.logger.init("photobucket");
- if (!gPhotobucketAPI) {
- gPhotobucketAPI = new PhotobucketAPI();
- }
- this.api = gPhotobucketAPI;
- this._ctk = {
- interfaces: [
- "nsISupports",
- "flockIWebServiceAccount",
- "flockIMediaWebServiceAccount",
- "flockIMediaUploadAccount"
- ]
- };
- getCompTK().addAllInterfaces(this);
- }
-
- // BEGIN flockIWebServiceAccount interface
- photobucketAccount.prototype.urn = null;
-
- photobucketAccount.prototype.login =
- function photobucketAccount_login(aListener)
- {
- this.logger.debug("{flockIWebServiceAccount}.login() urn=" + this.urn);
-
- var timer = Components.classes["@mozilla.org/timer;1"]
- .createInstance(Ci.nsITimer);
- var inst = this;
- timerFunc = {
- notify: function(aTimer) {
- inst.api.doLogin(inst.urn, aListener);
- }
- }
- timer.initWithCallback(timerFunc, 0, 0); //re-check token
- }
-
- photobucketAccount.prototype.activate =
- function photobucketAccount_activate(aListener)
- {
- this.logger.debug("{flockIWebServiceAccount}.activate() urn=" + this.urn);
- var acctCoopObj = this._coop.get(this.urn);
- var inst = this;
- var listener = {
- onSuccess: function() {
- inst.logger.debug("activate() listener onAuth()");
- acctCoopObj.isPollable = true;
- aListener.onSuccess(inst, "accountAuthorized");
- try {
- var authUser = inst.api.mAuthUser;
- acctCoopObj.name = authUser.fullname;
- var photostreamURN = "urn:flock:stream:photo:photobucket:"+acctCoopObj.accountId;
- var photostream = inst._coop.get(photostreamURN);
- photostream.name = authUser.fullname+" Photostream";
- } catch (ex) {
- inst.logger.error(ex + '::' + ex.lineNumber);
- }
- },
- onError: function(aError) {
- inst.logger.debug("activate() listener onError()");
- try {
- var authUser = inst.getAuthUser();
- var acctCoopObj = inst._coop.get(inst.urn);
- acctCoopObj.isAuthenticated = false;
- } catch (ex) {
- // Don't really need to do anything, we were just trying to be nice
- // anyway...
- }
- }
- }
- this.login(listener);
- // Pre-emptively setting isAuthenticated to TRUE in order to avoid further
- // auth attemps while this one is completing.
- acctCoopObj.isAuthenticated = true;
- }
-
- photobucketAccount.prototype.deactivate =
- function photobucketAccount_deactivate()
- {
- this.logger.debug("{flockIWebServiceAccount}.deactivate()");
- var acctCoopObj = this._coop.get(this.urn);
- acctCoopObj.isPollable = false;
- acctCoopObj.isAuthenticated = false;
- }
-
- photobucketAccount.prototype.keep =
- function photobucketAccount_keep()
- {
- var c_acct = this._coop.get(this.urn);
- c_acct.isTransient = false;
- }
- // END flockIWebServiceAccount interface
-
- // ========== END photobucketAccount class ==========
-